/*
ES6 借鉴 C++、Java、C# 和 Python 语言，引入了for...of循环，作为遍历所有数据结构的统一的方法。

一个数据结构只要部署了Symbol.iterator属性，就被视为具有 iterator 接口，就可以用for...of循环遍历它的成员。
也就是说，for...of循环内部调用的是数据结构的Symbol.iterator方法。

for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象（比如arguments对象、DOM NodeList 对象）、
后文的 Generator 对象，以及字符串。
*/

/*
数组原生具备iterator接口（ 即默认部署了Symbol.iterator属性），
for...of循环本质上就是调用这个接口产生的遍历器， 可以用下面的代码证明。
空对象obj部署了数组arr的Symbol.iterator属性， 结果obj的for...of循环， 产生了与arr完全一样的结果。
*/
const arr = ['red', 'green', 'blue'];

for (let v of arr) {
	console.log(v); // red green blue
}

const obj = {};
obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr); // 指定部署数组arr的Symbol.iterator属性

for (let v of obj) {
	console.log(v); // red green blue
}



//for...of循环可以代替数组实例的forEach方法。
const arr = ['red', 'green', 'blue'];
arr.forEach(function(element, index) {
	console.log(element); // red green blue
	console.log(index); // 0 1 2
});



/*
JavaScript 原有的for...in循环，只能获得对象的键名，不能直接获取键值。
ES6 提供for...of循环，允许遍历获得键值。

看多了以后 for..in  for..of  的不同作用明朗多了
下面代码表明，for...in循环读取键名，for...of循环读取键值。
如果要通过for...of循环，获取数组的索引，
可以借助数组实例的entries方法和keys方法（参见《数组的扩展》一章）。
*/
var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
	console.log(a); // 0 1 2 3
}

for (let a of arr) {
	console.log(a); // a b c d
}




/*
for...of循环调用遍历器接口，数组的遍历器接口只返回具有数字索引的属性。
这一点跟for...in循环也不一样。
下面代码中，for...of循环不会返回数组arr的foo属性。
*/
let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) { //偏向于对象结构的循环
	console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) { //严格遵守各数据结构默认的遍历器走
	console.log(i); //  "3", "5", "7"  
}
